<?php
/***********************************************************************
 * @package     IvanEngine
 * @subpackage  Framework
 * @author      Ivan <ivanzx@msn.com>
 * @created     2010-06-05
 ***********************************************************************/
if(defined("IVANENGINE_FRAMEWORK_WINDOW"))
    die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_FRAMEWORK_WINDOW", true);

require_once (dirname(__FILE__).'/Common.php');
require_once (dirname(__FILE__).'/WindowModifier.php');

class CWindow extends CTree
{
    const ROOT_NAME         = 'windows';
    
    const WS_MIN            = 0x1;
    const WS_MAX            = 0x2;
    const WS_CLOSE          = 0x4;
    
    const WA_TAG            = 'window';
    const WA_NAME           = 'name';
    const WA_TITLE          = 'title';
    const WA_ALIGN          = 'align';
    const WA_POSMY          = 'posMy';
    const WA_POSX           = 'posX';
    const WA_POSY           = 'posY';
    const WA_WIDTH          = 'width';
    const WA_HEIGHT         = 'height';
    const WA_MAXWIDTH       = 'maxWidth';
    const WA_MAXHEIGHT      = 'maxHeight';
    const WA_MINWIDTH       = 'minWidth';
    const WA_MINHEIGHT      = 'minHeight';
    const WA_AUTOOPTN       = 'autoOpen';
    const WA_VISIBLE        = 'visible';
    const WA_ALPHA          = 'alpha';
    const WA_DRAGALPHA      = 'dragAlpha';
    const WA_ZINDEX         = 'zIndex';
    const WA_MODAL          = 'modal';
    const WA_DRAGGABLE      = 'draggable';
    const WA_RESIZABLE      = 'resizable';
    const WA_TITLEBAR       = 'titlebar';
    const WA_AlWAYTOP       = 'alwayTop';
    const WA_WINSTYLE       = 'winStyle';
    const WA_BORDERSTYLE    = 'borderStyle';
    const WA_STYLECLASS     = 'styleClass';
    const WA_SHOWANIM       = 'showAnim';
    const WA_HIDEANIM       = 'hideAnim';
    const WA_CLOSETEXT      = 'closeText';
    const WA_MAXBOXTEXT     = 'maxboxText';
    const WA_MINBOXTEXT     = 'minboxText';

    protected
        $m_id           = '',
        $m_title        = 'window',
        $m_align        = 'left top',
        $m_posMy        = 'left top',
        $m_posX         = 0,
        $m_posY         = 0,
        $m_width        = 200,
        $m_height       = 200,
        $m_maxWidth     = 0,
        $m_maxHeight    = 0,
        $m_minWidth     = 200,
        $m_minHeight    = 200,
        $m_alpha        = 1,
        $m_dragAlpha    = 0.8,
        $m_zIndex       = 1,
        $m_visible      = true,
        $m_modal        = false,
        $m_autoOpen     = true,
        $m_draggable    = false,
        $m_resizable    = false,
        $m_titlebar     = true,
        $m_alwayTop     = false,
        $m_winStyle     = self::WS_CLOSE,
        $m_styleClass   = 'ui-window',
        $m_borderStyle  = '',
        $m_showAnim     = '',
        $m_hideAnim     = '',
        $m_closeText    = 'close',
        $m_maxboxText   = 'max',
        $m_minboxText   = 'min',
        $m_jsFilePath   = '';
        
    static public $ms_attrList  = null;
    static public $ms_jsWarp    = '';
        
    public function __construct($name)
    {
        parent::__construct($name);
        $this->m_id         = self::ID($name);
        $this->m_title      = $name;
        $this->m_winStyle   |= self::WS_MIN | self::WS_MAX;
        CWindowManager::Get()->AddWindow($this);
    }
    
    public function __destruct()
    {
        parent::__destruct();
    }
    
    public function SetName($name)
    {
        throw new CException('Window name can not reset.');
    }
    
    public function GetID()
    {
        return $this->m_id;
    }
    
    public function SetTitle($title)
    {
        $this->m_title  = $title;
    }
    
    public function GetTitle()
    {
        return $this->m_title;
    }
    
    public function SetAlign($align)
    {
        $this->m_align  = $align;
    }
    
    public function GetAlign()
    {
        return $this->m_align;
    }
    
    public function SetPosMy($posMy)
    {
        $this->m_posMy  = $posMy;
    }
    
    public function GetPosMy()
    {
        return $this->m_posMy;
    }
    
    public function SetPosX($posX)
    {
        $this->m_posX  = $posX;
    }
    
    public function GetPosX()
    {
        return $this->m_posX;
    }
    
    public function SetPosY($posY)
    {
        $this->m_posY  = $posY;
    }
    
    public function GetPosY()
    {
        return $this->m_posY;
    }
    
    public function SetWidth($width)
    {
        $this->m_width  = $width;
    }
    
    public function GetWidth()
    {
        return $this->m_width;
    }
    
    public function SetHeight($height)
    {
        $this->m_height  = $height;
    }
    
    public function GetHeight()
    {
        return $this->m_height;
    }
    
    public function SetMaxWidth($maxWidth)
    {
        $this->m_maxWidth  = $maxWidth;
    }
    
    public function GetMaxWidth()
    {
        return $this->m_maxWidth;
    }
    
    public function SetMaxHeight($maxHeight)
    {
        $this->m_maxHeight  = $maxHeight;
    }
    
    public function GetMaxHeight()
    {
        return $this->m_maxHeight;
    }
    
    public function SetMinWidth($minWidth)
    {
        $this->m_minWidth  = $minWidth;
    }
    
    public function GetMinWidth()
    {
        return $this->m_minWidth;
    }
    
    public function SetMinHeight($minHeight)
    {
        $this->m_minHeight  = $minHeight;
    }
    
    public function GetMinHeight()
    {
        return $this->m_minHeight;
    }
    
    public function SetAlpha($alpha)
    {
        $this->m_alpha  = $alpha;
    }
    
    public function GetAlpha()
    {
        return $this->m_alpha;
    }
    
    public function SetDragAlpha($alpha)
    {
        $this->m_dragAlpha  = $alpha;
    }
    
    public function GetDragAlpha()
    {
        return $this->m_dragAlpha;
    }
    
    public function SetZIndex($zIndex)
    {
        $this->m_zIndex  = $zIndex;
    }
    
    public function GetZIndex()
    {
        return $this->m_zIndex;
    }
    
    public function SetWinStyle($winStyle)
    {
        $resultCode = 0;
        if( CStringHelper::FindFirstOf('WS_CLOSE', $winStyle) != CString::npos ){
            $resultCode = $resultCode | CWindow::WS_CLOSE;
        }
        if( CStringHelper::FindFirstOf('WS_MAX', $winStyle) != CString::npos ){
            $resultCode = $resultCode | CWindow::WS_MAX;
        }
        if( CStringHelper::FindFirstOf('WS_MIN', $winStyle) != CString::npos ){
            $resultCode = $resultCode | CWindow::WS_MIN;
        }
        $this->m_winStyle  = $resultCode;
    }
    
    public function GetWinStyle()
    {
        return $this->m_winStyle;
    }
    
    public function SetAutoOpen($autoOpen)
    {
        $this->m_autoOpen= CStringHelper::ToBool($autoOpen);
    }
    
    public function GetAutoOpen()
    {
        return $this->m_autoOpen;
    }
    
    public function SetVisible($visible)
    {
        $this->m_visible= CStringHelper::ToBool($visible);
    }
    
    public function GetVisible()
    {
        return $this->m_visible;
    }
    
    public function SetModal($modal)
    {
        $this->m_modal= CStringHelper::ToBool($modal);
    }
    
    public function GetModal()
    {
        return $this->m_modal;
    }
    
    public function SetDraggable($draggable)
    {
        $this->m_draggable  = CStringHelper::ToBool($draggable);
    }
    
    public function GetDraggable()
    {
        return $this->m_draggable;
    }
    
    public function SetResizable($resizable)
    {
        $this->m_resizable  = CStringHelper::ToBool($resizable);
    }
    
    public function GetResizable()
    {
        return $this->m_resizable;
    }
    
    public function SetTitleBar($hasTitleBar)
    {
        $this->m_titlebar  = CStringHelper::ToBool($hasTitleBar);
    }
    
    public function GetTitleBar()
    {
        return $this->m_titlebar;
    }
    
    public function SetAlwayTop($setting)
    {
        $this->m_alwayTop   = CStringHelper::ToBool($setting);
    }
    
    public function GetAlwayTop()
    {
        return $this->m_alwayTop;
    }
    
    public function SetStyleClass($class)
    {
        $this->m_styleClass  = $class;
    }
    
    public function GetStyleClass()
    {
        return $this->m_styleClass;
    }
    
    public function SetBorderStyle($style)
    {
        $this->m_borderStyle    = $style;
    }
    
    public function GetBorderStyle()
    {
        return $this->m_borderStyle;
    }
    
    public function SetShowAnim($animStr)
    {
        $this->m_showAnim  = $animStr;
    }
    
    public function GetShowAnim()
    {
        return $this->m_showAnim;
    }
    
    public function SetHideAnim($animStr)
    {
        $this->m_hideAnim  = $animStr;
    }
    
    public function GetHideAnim()
    {
        return $this->m_hideAnim;
    }
    
    public function SetCloseText($closeText)
    {
        $this->m_closeText  = $closeText;
    }
    
    public function GetCloseText()
    {
        return $this->m_closeText;
    }
    
    public function SetMaxBoxText($maxboxText)
    {
        $this->m_maxboxText  = $maxboxText;
    }
    
    public function GetMaxBoxText()
    {
        return $this->m_maxboxText;
    }
    
    public function SetMinBoxText($minBoxText)
    {
        $this->m_minboxText  = $minBoxText;
    }
    
    public function GetMinBoxText()
    {
        return $this->m_minboxText;
    }
    
    public function CreateWindow($winName)
    {
        $win    = CWindowManager::Get()->GetWindow($winName);
        if( $win == null ){
            $win    = new CWindow($winName);
            $this->AddChild($win);
        }else if($win->GetParent() != $this){
            $win->GetParent()->RemoveChild($win->GetName());
            $this->AddChild($win);
            //CLog::Get()->Warning('CWindow::CreateWindow("'.$winName.'") Warning:<br>'.
            //  'the window already exsit and it is not the "'.$this->GetName().'" of child.');
        }
        return $win;
    }
    
    public function FromXmlNode(CXmlNode & $node)
    {
        foreach( $node->GetAttributes() as $name => $value ){
            if( !method_exists($this, 'Set'.ucfirst($name)) ){
                continue;
            }
            if( $name == 'name' ){
                parent::SetName($value);
            }else{
                call_user_func(array($this, 'Set'.ucfirst($name)), $value);
            }
        }
        
        foreach( $node->GetChilds() as $name => $child )
        {
            $winChild = $this->CreateWindow($name);
            $winChild->FromXmlNode($child);
        }
    }
    
    public function Render($inHtml = true, $renderChild = true)
    {
        if( $inHtml == true ){
            $htmlContent  = $this->_GetHtmlCode($renderChild);
            $htmlContent  = $htmlContent.M_WARP.HTag::ContentTag(
                'script', M_WARP.$this->_GetJSCode($renderChild).M_WARP).M_WARP;
        }else{
            $htmlContent  = '$(\'body\').append(\''.$this->_GetHtmlCode($renderChild).'\');';
            $htmlContent  = $htmlContent.M_WARP.$this->_GetJSCode($renderChild).M_WARP;
        }
        
        CWindowManager::Get()->AddToStorage($this->GetName());
        
        return $htmlContent;
    }
    
    protected function _GetHtmlCode($includeChild = true)
    {
        // render html code of the window
        if( $this != CWindowManager::Get()->GetRoot() ){
            $divContent = '<div id="'.$this->m_id.'">';
        }
        
        // render html code of child windows
        if( $includeChild )
        {
            $it = $this->m_childMap->Begin();
            for(; !$it->IsEnd(); $it->Next())
            {
                $divContent .=$it->Value()->_GetHtmlCode();
            }
        }
        if( $this != CWindowManager::Get()->GetRoot() ){
            $divContent .='</div>';
        }
        return $divContent;
    }
    
    protected function _GetJSCode($includeChild = true)
    {
        if( $this != CWindowManager::Get()->GetRoot() )
        {
            $warp   = self::$ms_jsWarp;
            $jsContent  = '$(\'#'.$this->m_id.'\').window({'.$warp;
            if($this->m_parent != null && $this->m_parent != CWindowManager::Get()->GetRoot() ){
                $jsContent  .='containment:\'#'.self::WA_TAG.'_'.$this->m_parent->m_name.'\','.$warp;
            }else{
                $jsContent  .='containment:"document",'.$warp;
            }
            
            if( $this->GetShowAnim() != '')
            {
                if( substr($this->GetShowAnim(), 0, 8) == 'function')
                    $jsContent  .= self::WA_SHOWANIM    .':'.$this->GetShowAnim().','.$warp;
                else
                    $jsContent  .= self::WA_SHOWANIM    .':\''.$this->GetShowAnim().'\','.$warp;
            }
            if( $this->GetHideAnim() != '')
            {
                if( substr($this->GetHideAnim(), 0, 8) == 'function')
                    $jsContent  .= self::WA_HIDEANIM    .':'.$this->GetHideAnim().','.$warp;
                else
                    $jsContent  .= self::WA_HIDEANIM    .':"'.$this->GetHideAnim().'",'.$warp;
            }
            
            for( $it = self::$ms_attrList->Begin(); !$it->IsEnd(); $it->Next() )
            {
                if( $it->Value() == self::WA_SHOWANIM ||
                    $it->Value() == self::WA_HIDEANIM)
                {
                    continue;
                }
                $jsContent .= $it->Value().':'.CWindow::FormatToJsValue($it->Value(), 
                        $this->GetValue($it->Value())).','.$warp;
            }
            $jsContent  = substr($jsContent, 0, strlen($jsContent)-(1+strlen($warp))).$warp;
            $jsContent  .= '});'.$warp;
        }
        // update child windows
        if( $includeChild )
        {
            $it = $this->m_childMap->Begin();
            for(; !$it->IsEnd(); $it->Next())
            {
                $jsContent  .= $it->Value()->_GetJSCode();
            }
        }
        
        return $jsContent;
    }
    
    public function AddChildToManager()
    {
        foreach( $this->m_childMap as $child )
        {
            CWindowManager::Get()->AddWindow($child);
            $child->AddChildToManager();
        }
    }
    
    public function GetValue($attrName)
    {
        $funName    = 'Get'.ucfirst($attrName);
        if( !method_exists($this, $funName) )
        {
            throw new CExceptionInvalidArgument(
                'Windows do not have this property: '.$funName);
        }
        return call_user_func(array($this, $funName));
    }
    
    static public function ID($name)
    {
        return self::WA_TAG.'_'.$name;
    }
    
    static public function FormatToJsValue($key, $value)
    {
        if( $key == self::WA_WIDTH || $key == self::WA_HEIGHT ){
            if( !is_numeric($value) ){
                return '\''.$value.'\'';
            }else{
                return $value;
            }
        }
        switch($key)
        {
            case self::WA_NAME:
            case self::WA_TITLE:
            case self::WA_ALIGN :
            case self::WA_POSMY:
            case self::WA_WINSTYLE:
            case self::WA_BORDERSTYLE:
            case self::WA_STYLECLASS :
            case self::WA_SHOWANIM:
            case self::WA_HIDEANIM:
            case self::WA_CLOSETEXT:
            case self::WA_MAXBOXTEXT:
            case self::WA_MINBOXTEXT:
                return '\''.$value.'\'';
            case self::WA_VISIBLE:
            case self::WA_MODAL:
            case self::WA_AUTOOPTN:
            case self::WA_DRAGGABLE:
            case self::WA_RESIZABLE:
            case self::WA_TITLEBAR:
            case self::WA_AlWAYTOP:
                return $value ? 'true' : 'false';
            default:
                return $value;
        }
    }
    
    static public function & AttributeKeys()
    {
        return self::$ms_attrList;
    }
    
    static public function _AddAttrToList()
    {
        if( self::$ms_attrList ){
            return;
        }
        self::$ms_attrList  = new CVector();
        self::$ms_attrList->Add(self::WA_NAME);
        self::$ms_attrList->Add(self::WA_TITLE);
        self::$ms_attrList->Add(self::WA_ALIGN );
        self::$ms_attrList->Add(self::WA_POSMY);
        self::$ms_attrList->Add(self::WA_POSX);
        self::$ms_attrList->Add(self::WA_POSY);
        self::$ms_attrList->Add(self::WA_WIDTH);
        self::$ms_attrList->Add(self::WA_HEIGHT);
        self::$ms_attrList->Add(self::WA_MAXWIDTH);
        self::$ms_attrList->Add(self::WA_MAXHEIGHT);
        self::$ms_attrList->Add(self::WA_MINWIDTH);
        self::$ms_attrList->Add(self::WA_MINHEIGHT);
        self::$ms_attrList->Add(self::WA_AUTOOPTN);
        self::$ms_attrList->Add(self::WA_VISIBLE);
        self::$ms_attrList->Add(self::WA_ALPHA);
        self::$ms_attrList->Add(self::WA_DRAGALPHA);
        self::$ms_attrList->Add(self::WA_ZINDEX);
        self::$ms_attrList->Add(self::WA_MODAL);
        self::$ms_attrList->Add(self::WA_DRAGGABLE);
        self::$ms_attrList->Add(self::WA_RESIZABLE);
        self::$ms_attrList->Add(self::WA_TITLEBAR);
        self::$ms_attrList->Add(self::WA_AlWAYTOP);
        self::$ms_attrList->Add(self::WA_WINSTYLE);
        self::$ms_attrList->Add(self::WA_BORDERSTYLE);
        self::$ms_attrList->Add(self::WA_STYLECLASS );
        self::$ms_attrList->Add(self::WA_SHOWANIM);
        self::$ms_attrList->Add(self::WA_HIDEANIM);
        self::$ms_attrList->Add(self::WA_CLOSETEXT);
        self::$ms_attrList->Add(self::WA_MAXBOXTEXT);
        self::$ms_attrList->Add(self::WA_MINBOXTEXT);
    }
}

?>
